import mx.utils.Delegate;

import org.molamil.acto.core.Logger;
import org.molamil.acto.mc.McTargetResolver;
import org.molamil.acto.mc.mcw.LcMcWrapper;
import org.molamil.acto.pages.InvalidContainerError;
import org.molamil.acto.pages.master.AbstractMovieMaster;
import org.molamil.commons.ObjectUtil;
import org.molamil.commons.StringUtil;

/**
 * @author Jorge Hernandez
 */
class org.molamil.acto.pages.master.AbstractExternalMaster extends AbstractMovieMaster {

	
	// Properties
	
	private static var log:Logger = Logger.getLogger("AbstractExternalMaster");
	
	public static var ERROR_INVALID_CONTAINER:String = "ERROR: The container MovieClip path is invalid: \"{container}\".";
	
	private var mcLoader:MovieClipLoader;
	private var loadTarget_mc:MovieClip;
	private var isLoading:Boolean;
	
	private var loadStartDelegate:Function;
	private var loadProgressDelegate:Function;
	private var loadInitDelegate:Function;
	private var loadErrorDelegate:Function;
	
	
	// Constructor
	
	public function AbstractExternalMaster() {
		log.debug("Constructor");
		isLoading = false;
		loadStartDelegate = Delegate.create(this, onLoadStartListener);
		loadProgressDelegate = Delegate.create(this, onLoadProgressListener);
		loadInitDelegate = Delegate.create(this, onLoadInitListener);
		loadErrorDelegate = Delegate.create(this, onLoadErrorListener);
	}
	
	
	// Functions
	
	public function display():Void {
		
		log.info("display(), name = " + context.name);
		
		log.debug("mcWrapper = " + mcWrapper);
		
		var container_mc:MovieClip = _root;
		if (context.container != null)
			container_mc = McTargetResolver.getMc(context.container);
		loadTarget_mc = container_mc.createEmptyMovieClip(context.name, container_mc.getNextHighestDepth());
		if (loadTarget_mc == null) {
			var msg:String = StringUtil.replace(ERROR_INVALID_CONTAINER, "{container}", context.container);
			throw new InvalidContainerError(msg);
		}
		
		mcLoader = new MovieClipLoader();
		var listener:Object = new Object();
		listener.onLoadStart = loadStartDelegate;
		listener.onLoadProgress = loadProgressDelegate;		
		listener.onLoadInit = loadInitDelegate;
		listener.onLoadError = loadErrorDelegate;
		mcLoader.addListener(listener);
		
		log.debug("target = " + context.target);
		log.debug("loadTarget_mc = " + loadTarget_mc);
		
		mcLoader.loadClip(context.target, loadTarget_mc);
		isLoading = true;
		
	}
	
	public function clear():Void {
		
		log.info("clear(), name = " + context.name);
		log.debug("isLoading = " + isLoading);
		
		if (isLoading) {
			unloadMc();
		} else {
			mcWrapper.state = LcMcWrapper.STATE_OUT;
		}
		
	}
	
	private function unloadMc():Void {
		
		log.debug("unloadMc(), loadTarget_mc = " + loadTarget_mc);
		
		mcLoader.unloadClip(loadTarget_mc);
		loadTarget_mc.removeMovieClip();
		loadTarget_mc = null;
		isLoading = false;
		_isDisplayed = false;
		
		log.debug("mcWrapper.mc deleted");
		
	}
	
	private function onLoadStartListener(target_mc:MovieClip):Void {
		log.warning("[Abstract] onLoadStartListener() to be implemented.");
	}
	
	private function onLoadProgressListener(target_mc:MovieClip, bytesLoaded:Number, 
											bytesTotal:Number):Void {
		log.warning("[Abstract] onLoadProgressListener() to be implemented.");
	}
	
	private function onLoadInitListener(target_mc:MovieClip):Void {
		
		log.debug("onLoadInitListener(), name = " + context.name);
		
		isLoading = false;
		_isDisplayed = true;
		
		log.debug("context.base = " + context.base);
		
		if (context.base == null) {
			mcWrapper.mc = loadTarget_mc;
		} else {
			mcWrapper.mc = McTargetResolver.getMc(context.base, loadTarget_mc);
		}
		
		log.debug("onLoadInitListener(), mcWrapper.mc = " + mcWrapper.mc);
		
	}

	private function onLoadErrorListener(target_mc:MovieClip, errorCode:String, 
										 httpStatus:Number):Void {
										 	
		log.warning("onLoadErrorListener(), name = " + context.name);
		
		isLoading = false;
		
	}
	
	private function doInit():Void {
		ObjectUtil.merge(mcWrapper.mc, context.props);
		ObjectUtil.merge(mcWrapper.mc, request.params);
		mcWrapper.state = LcMcWrapper.STATE_IN;
	}
	
	private function mcStateChangeListener(eventObject:Object):Void {
		
		super.mcStateChangeListener(eventObject);
		
		log.debug("mcStateChangeListener(), name = " + context.name);
		log.debug("state = " + eventObject.state);
		
		if (eventObject.state == LcMcWrapper.STATE_OFF)
			unloadMc();
			
	}
	
	
}
